dash_charts.utils_app_with_navigation⚓︎
Classes for more complex applications that have tabbed or paged navigation.
View Source
"""Classes for more complex applications that have tabbed or paged navigation."""
from collections import OrderedDict
from copy import deepcopy
import dash_bootstrap_components as dbc
from dash import dcc, html
from implements import implements
from .utils_app import AppBase, AppInterface
TODO_CLIENT_CALLBACK = '''
TODO: Create clientside callbacks dynamically to update the title on navigation
See: http://dash.plotly.com/external-resources
```py
app.clientside_callback(
"""
function(tab_value) {
if (tab_value === 'tab-1') {
document.title = 'Tab 1'
} else if (tab_value === 'tab-2') {
document.title = 'Tab 2'
}
}
""",
Output('blank-output', 'children'),
[Input('tabs-example', 'value')]
)
TODO: Try to see if I can resolve the interface differences or if I need make a subclass interface⚓︎
@implements(AppInterface) # noqa: H601⚓︎
class AppWithNavigation(AppBase): “”“Base class for building Dash Application with tabs or URL routing.”“”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
@implements(AppInterface) # noqa: H601 class StaticTab(AppBase): “”“Simple App without charts or callbacks.”“”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
class AppWithTabs(AppWithNavigation): “”“Base class for building Dash Application with tabs.”“”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
> PLANNED: Make the tabs and chart compact as well when the compact argument is set to True⚓︎
class FullScreenAppWithTabs(AppWithTabs): # noqa: H601 “”“Base class for building Dash Application with tabs that uses the full window.”“”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
class AppMultiPage(AppWithNavigation): # noqa: H601 “”“Base class for building Dash Application with multiple pages.”“”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
```
Variables⚓︎
TODO_CLIENT_CALLBACK
Classes⚓︎
AppMultiPage⚓︎
class AppMultiPage(
app: Union[dash.dash.Dash, NoneType] = None
)
View Source
class AppMultiPage(AppWithNavigation): # noqa: H601
"""Base class for building Dash Application with multiple pages."""
navbar_links = None
"""Base class must create list of tuples `[('Link Name', '/link'), ]` to use default `self.nav_bar()`."""
dropdown_links = None
"""Base class must create list of tuples `[('Link Name', '/link'), ]` to use default `self.nav_bar()`."""
logo = None
"""Optional path to logo. If None, no logo will be shown in navbar."""
# App ids
id_url = 'pages-url'
id_pages_content = 'pages-wrapper'
id_toggler = 'nav-toggle'
id_collapse = 'nav-collapse'
app_ids = [id_url, id_pages_content, id_toggler, id_collapse]
"""List of all ids for the top-level pages view. Will be mapped to `self._il` for globally unique ids."""
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object
"""
return html.Div(
children=[
dcc.Location(id=self._il[self.id_url], refresh=False),
self.nav_bar(),
html.Div(id=self._il[self.id_pages_content]),
],
)
def nav_bar(self):
"""Return the HTML elements for the navigation menu.
Returns:
dict: Dash HTML object
"""
# Create brand icon and name where icon in optional
brand = []
if self.logo:
brand.append(dbc.Col(html.Img(src=self.logo, height='25px')))
brand.append(dbc.Col(dbc.NavbarBrand(self.name, className='ml-2')))
# Create links in navbar and dropdown. Both are optional
links = []
if self.navbar_links:
links.append(
dbc.Nav(
children=[dbc.NavItem(dbc.NavLink(name, href=link)) for name, link in self.navbar_links],
fill=True,
navbar=True,
),
)
if self.dropdown_links:
links.append(
dbc.Nav(
dbc.DropdownMenu(
children=[dbc.DropdownMenuItem(name, href=link) for name, link in self.dropdown_links],
in_navbar=True,
label='Links',
nav=True,
),
navbar=True,
),
)
# Layout default navbar
return dbc.Navbar(
children=[
dbc.NavLink(
[
dbc.Row(
children=brand,
align='center g-0',
),
], href='/',
),
dbc.NavbarToggler(id=self._il[self.id_toggler]),
dbc.Collapse(
dbc.Row(
children=links,
className='flex-nowrap mt-3 mt-md-0 g-0',
align='center',
),
id=self._il[self.id_collapse],
navbar=True,
),
],
sticky='top',
color='dark',
dark=True,
)
def create_callbacks(self) -> None:
"""Register the navigation callback."""
outputs = [(self.id_pages_content, 'children')]
inputs = [(self.id_url, 'pathname')]
@self.callback(outputs, inputs, [])
def render_page(pathname):
try:
# TODO: Demo how pages could use parameters from pathname
return [self.nav_layouts[self.select_page_name(pathname)]]
except Exception as err:
return [html.Div(children=[f'Error rendering "{pathname}":\n{err}'])]
@self.callback(
[(self.id_collapse, 'is_open')],
[(self.id_toggler, 'n_clicks')],
[(self.id_collapse, 'is_open')],
)
def toggle_navbar_collapse(n_clicks, is_open):
return [not is_open if n_clicks else is_open]
def select_page_name(self, pathname):
"""Return the page name determined based on the pathname.
Should return str: page name
Args:
pathname: relative pathname from URL
Raises:
NotImplementedError: Child class must implement this method
"""
raise NotImplementedError('nav_bar must be implemented by child class') # pragma: no cover
Ancestors (in MRO)⚓︎
- dash_charts.utils_app_with_navigation.AppWithNavigation
- dash_charts.utils_app.AppBase
Class variables⚓︎
app
app_ids
List of all ids for the top-level pages view. Will be mapped to self._il for globally unique ids.
dropdown_links
Base class must create list of tuples [('Link Name', '/link'), ] to use default self.nav_bar().
external_stylesheets
id_collapse
id_pages_content
id_toggler
id_url
init_app_kwargs
logo
Optional path to logo. If None, no logo will be shown in navbar.
modules
name
nav_layouts
nav_lookup
navbar_links
Base class must create list of tuples [('Link Name', '/link'), ] to use default self.nav_bar().
nsi
validation_layout
Methods⚓︎
callback⚓︎
def callback(
self,
outputs,
inputs,
states,
pic: bool = False,
**kwargs: dict
)
Return app callback decorator based on provided components.
Parameters:
| Name | Description |
|---|---|
| outputs | list of tuples with app_id and property name |
| inputs | list of tuples with app_id and property name |
| states | list of tuples with app_id and property name |
| pic | If True, prevent call on page load (prevent_initial_call). Default is False |
| **kwargs | any additional keyword arguments for self.app.callback |
Returns:
| Type | Description |
|---|---|
| dict | result of self.app.callback() |
View Source
def callback(self, outputs, inputs, states, pic: bool = False, **kwargs: dict):
"""Return app callback decorator based on provided components.
Args:
outputs: list of tuples with app_id and property name
inputs: list of tuples with app_id and property name
states: list of tuples with app_id and property name
pic: If True, prevent call on page load (`prevent_initial_call`). Default is False
**kwargs: any additional keyword arguments for `self.app.callback`
Returns:
dict: result of `self.app.callback()`
"""
return self.app.callback(
*format_app_callback(self._il, outputs, inputs, states),
prevent_initial_call=pic,
**kwargs,
)
create⚓︎
def create(
self,
**kwargs
)
Create each navigation componet, storing the layout. Then parent class to create application.
Parameters:
| Name | Description |
|---|---|
| kwargs | keyword arguments passed to self.create |
View Source
def create(self, **kwargs):
"""Create each navigation componet, storing the layout. Then parent class to create application.
Args:
kwargs: keyword arguments passed to `self.create`
"""
# Initialize the lookup for each tab then configure each tab
self.nav_lookup = OrderedDict([(tab.name, tab) for tab in self.define_nav_elements()])
self.nav_layouts = {}
for nav_name, nav in self.nav_lookup.items():
nav.create(assign_layout=False)
self.nav_layouts[nav_name] = nav.return_layout()
# Store validation_layout that is later used for callback verification in base class
self.validation_layout = [*map(deepcopy, self.nav_layouts.values())]
# Initialize parent application that handles navigation
super().create(**kwargs)
create_callbacks⚓︎
def create_callbacks(
self
) -> None
Register the navigation callback.
View Source
def create_callbacks(self) -> None:
"""Register the navigation callback."""
outputs = [(self.id_pages_content, 'children')]
inputs = [(self.id_url, 'pathname')]
@self.callback(outputs, inputs, [])
def render_page(pathname):
try:
# TODO: Demo how pages could use parameters from pathname
return [self.nav_layouts[self.select_page_name(pathname)]]
except Exception as err:
return [html.Div(children=[f'Error rendering "{pathname}":\n{err}'])]
@self.callback(
[(self.id_collapse, 'is_open')],
[(self.id_toggler, 'n_clicks')],
[(self.id_collapse, 'is_open')],
)
def toggle_navbar_collapse(n_clicks, is_open):
return [not is_open if n_clicks else is_open]
create_elements⚓︎
def create_elements(
self
) -> None
Override method as not needed at navigation-level.
View Source
def create_elements(self) -> None:
"""Override method as not needed at navigation-level."""
... # pragma: no cover
define_nav_elements⚓︎
def define_nav_elements(
self
)
Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex [AppBase(self.app)] in the order each tab is rendered
Raises:
| Type | Description |
|---|---|
| NotImplementedError | Child class must implement this method |
View Source
def define_nav_elements(self):
"""Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex `[AppBase(self.app)]` in the order each tab is rendered
Raises:
NotImplementedError: Child class must implement this method
"""
raise NotImplementedError('define_nav_elements must be implemented by child class') # pragma: no cover
generate_data⚓︎
def generate_data(
self
) -> None
Recommended method for generating data stored in memory. Called in initialization.
View Source
def generate_data(self) -> None:
"""Recommended method for generating data stored in memory. Called in initialization."""
...
get_server⚓︎
def get_server(
self
)
Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
| Type | Description |
|---|---|
| dict | the Flask server component of the Dash app |
View Source
def get_server(self):
"""Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
dict: the Flask `server` component of the Dash app
"""
return self.app.server
initialization⚓︎
def initialization(
self
) -> None
Initialize ids with self.register_uniq_ids([...]) and other one-time actions.
View Source
def initialization(self) -> None:
"""Initialize ids with `self.register_uniq_ids([...])` and other one-time actions."""
super().initialization()
self.register_uniq_ids(self.app_ids)
nav_bar⚓︎
def nav_bar(
self
)
Return the HTML elements for the navigation menu.
Returns:
| Type | Description |
|---|---|
| dict | Dash HTML object |
View Source
def nav_bar(self):
"""Return the HTML elements for the navigation menu.
Returns:
dict: Dash HTML object
"""
# Create brand icon and name where icon in optional
brand = []
if self.logo:
brand.append(dbc.Col(html.Img(src=self.logo, height='25px')))
brand.append(dbc.Col(dbc.NavbarBrand(self.name, className='ml-2')))
# Create links in navbar and dropdown. Both are optional
links = []
if self.navbar_links:
links.append(
dbc.Nav(
children=[dbc.NavItem(dbc.NavLink(name, href=link)) for name, link in self.navbar_links],
fill=True,
navbar=True,
),
)
if self.dropdown_links:
links.append(
dbc.Nav(
dbc.DropdownMenu(
children=[dbc.DropdownMenuItem(name, href=link) for name, link in self.dropdown_links],
in_navbar=True,
label='Links',
nav=True,
),
navbar=True,
),
)
# Layout default navbar
return dbc.Navbar(
children=[
dbc.NavLink(
[
dbc.Row(
children=brand,
align='center g-0',
),
], href='/',
),
dbc.NavbarToggler(id=self._il[self.id_toggler]),
dbc.Collapse(
dbc.Row(
children=links,
className='flex-nowrap mt-3 mt-md-0 g-0',
align='center',
),
id=self._il[self.id_collapse],
navbar=True,
),
],
sticky='top',
color='dark',
dark=True,
)
override_module_defaults⚓︎
def override_module_defaults(
self
) -> None
Override default values from modules.
View Source
def override_module_defaults(self) -> None:
"""Override default values from modules."""
...
register_uniq_ids⚓︎
def register_uniq_ids(
self,
app_ids: List[str]
) -> None
Register the app_ids to the corresponding global_id in the self._il lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers self._il
which are a list of globally unique ids (incorporating this App’s unique self.name) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Parameters:
| Name | Description |
|---|---|
| app_ids | list of strings that are unique within this App |
View Source
def register_uniq_ids(self, app_ids: List[str]) -> None:
"""Register the `app_ids` to the corresponding global_id in the `self._il` lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers `self._il`
which are a list of globally unique ids (incorporating this App's unique `self.name`) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Args:
app_ids: list of strings that are unique within this App
"""
self._il = deepcopy(self._il)
for app_id in app_ids:
self._il[app_id] = f'{self.name}-{app_id}'.replace(' ', '-')
return_layout⚓︎
def return_layout(
self
) -> dict
Return Dash application layout.
Returns:
| Type | Description |
|---|---|
| dict | Dash HTML object |
View Source
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object
"""
return html.Div(
children=[
dcc.Location(id=self._il[self.id_url], refresh=False),
self.nav_bar(),
html.Div(id=self._il[self.id_pages_content]),
],
)
run⚓︎
def run(
self,
**dash_kwargs: dict
) -> None
Launch the Dash server instance.
Parameters:
| Name | Description |
|---|---|
| **dash_kwargs | keyword arguments for Dash.run_server() |
View Source
def run(self, **dash_kwargs: dict) -> None:
"""Launch the Dash server instance.
Args:
**dash_kwargs: keyword arguments for `Dash.run_server()`
"""
self.app.run_server(**dash_kwargs) # pragma: no cover
select_page_name⚓︎
def select_page_name(
self,
pathname
)
Return the page name determined based on the pathname.
Should return str: page name
Parameters:
| Name | Description |
|---|---|
| pathname | relative pathname from URL |
Raises:
| Type | Description |
|---|---|
| NotImplementedError | Child class must implement this method |
View Source
def select_page_name(self, pathname):
"""Return the page name determined based on the pathname.
Should return str: page name
Args:
pathname: relative pathname from URL
Raises:
NotImplementedError: Child class must implement this method
"""
raise NotImplementedError('nav_bar must be implemented by child class') # pragma: no cover
verify_app_initialization⚓︎
def verify_app_initialization(
self
) -> None
Check that the app was properly initialized.
Raises:
| Type | Description |
|---|---|
| RuntimeError | if child class has not called self.register_uniq_ids |
View Source
def verify_app_initialization(self) -> None:
"""Check that the app was properly initialized.
Raises:
RuntimeError: if child class has not called `self.register_uniq_ids`
"""
if not self._il.keys(): # pragma: no cover
raise RuntimeError('Child class must first call `self.register_uniq_ids(__)` before self.run()')
AppWithNavigation⚓︎
class AppWithNavigation(
app: Union[dash.dash.Dash, NoneType] = None
)
View Source
class AppWithNavigation(AppBase):
"""Base class for building Dash Application with tabs or URL routing."""
app = None
"""Main Dash application to pass to all child tabs."""
nav_lookup = None
"""OrderedDict based on the list of tuples from `self.define_nav_elements()`."""
nav_layouts = None
"""Dictionary with nav_names as keys and corresponding layout as value."""
def define_nav_elements(self):
"""Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex `[AppBase(self.app)]` in the order each tab is rendered
Raises:
NotImplementedError: Child class must implement this method
"""
raise NotImplementedError('define_nav_elements must be implemented by child class') # pragma: no cover
def create(self, **kwargs):
"""Create each navigation componet, storing the layout. Then parent class to create application.
Args:
kwargs: keyword arguments passed to `self.create`
"""
# Initialize the lookup for each tab then configure each tab
self.nav_lookup = OrderedDict([(tab.name, tab) for tab in self.define_nav_elements()])
self.nav_layouts = {}
for nav_name, nav in self.nav_lookup.items():
nav.create(assign_layout=False)
self.nav_layouts[nav_name] = nav.return_layout()
# Store validation_layout that is later used for callback verification in base class
self.validation_layout = [*map(deepcopy, self.nav_layouts.values())]
# Initialize parent application that handles navigation
super().create(**kwargs)
def initialization(self) -> None:
"""Initialize ids with `self.register_uniq_ids([...])` and other one-time actions."""
super().initialization()
self.register_uniq_ids(self.app_ids)
def create_elements(self) -> None:
"""Override method as not needed at navigation-level."""
... # pragma: no cover
def create_callbacks(self) -> None:
"""Override method as not needed at navigation-level."""
... # pragma: no cover
Ancestors (in MRO)⚓︎
- dash_charts.utils_app.AppBase
Descendants⚓︎
- dash_charts.utils_app_with_navigation.AppWithTabs
- dash_charts.utils_app_with_navigation.AppMultiPage
Class variables⚓︎
app
Main Dash application to pass to all child tabs.
external_stylesheets
init_app_kwargs
modules
name
nav_layouts
Dictionary with nav_names as keys and corresponding layout as value.
nav_lookup
OrderedDict based on the list of tuples from self.define_nav_elements().
nsi
validation_layout
Methods⚓︎
callback⚓︎
def callback(
self,
outputs,
inputs,
states,
pic: bool = False,
**kwargs: dict
)
Return app callback decorator based on provided components.
Parameters:
| Name | Description |
|---|---|
| outputs | list of tuples with app_id and property name |
| inputs | list of tuples with app_id and property name |
| states | list of tuples with app_id and property name |
| pic | If True, prevent call on page load (prevent_initial_call). Default is False |
| **kwargs | any additional keyword arguments for self.app.callback |
Returns:
| Type | Description |
|---|---|
| dict | result of self.app.callback() |
View Source
def callback(self, outputs, inputs, states, pic: bool = False, **kwargs: dict):
"""Return app callback decorator based on provided components.
Args:
outputs: list of tuples with app_id and property name
inputs: list of tuples with app_id and property name
states: list of tuples with app_id and property name
pic: If True, prevent call on page load (`prevent_initial_call`). Default is False
**kwargs: any additional keyword arguments for `self.app.callback`
Returns:
dict: result of `self.app.callback()`
"""
return self.app.callback(
*format_app_callback(self._il, outputs, inputs, states),
prevent_initial_call=pic,
**kwargs,
)
create⚓︎
def create(
self,
**kwargs
)
Create each navigation componet, storing the layout. Then parent class to create application.
Parameters:
| Name | Description |
|---|---|
| kwargs | keyword arguments passed to self.create |
View Source
def create(self, **kwargs):
"""Create each navigation componet, storing the layout. Then parent class to create application.
Args:
kwargs: keyword arguments passed to `self.create`
"""
# Initialize the lookup for each tab then configure each tab
self.nav_lookup = OrderedDict([(tab.name, tab) for tab in self.define_nav_elements()])
self.nav_layouts = {}
for nav_name, nav in self.nav_lookup.items():
nav.create(assign_layout=False)
self.nav_layouts[nav_name] = nav.return_layout()
# Store validation_layout that is later used for callback verification in base class
self.validation_layout = [*map(deepcopy, self.nav_layouts.values())]
# Initialize parent application that handles navigation
super().create(**kwargs)
create_callbacks⚓︎
def create_callbacks(
self
) -> None
Override method as not needed at navigation-level.
View Source
def create_callbacks(self) -> None:
"""Override method as not needed at navigation-level."""
... # pragma: no cover
create_elements⚓︎
def create_elements(
self
) -> None
Override method as not needed at navigation-level.
View Source
def create_elements(self) -> None:
"""Override method as not needed at navigation-level."""
... # pragma: no cover
define_nav_elements⚓︎
def define_nav_elements(
self
)
Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex [AppBase(self.app)] in the order each tab is rendered
Raises:
| Type | Description |
|---|---|
| NotImplementedError | Child class must implement this method |
View Source
def define_nav_elements(self):
"""Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex `[AppBase(self.app)]` in the order each tab is rendered
Raises:
NotImplementedError: Child class must implement this method
"""
raise NotImplementedError('define_nav_elements must be implemented by child class') # pragma: no cover
generate_data⚓︎
def generate_data(
self
) -> None
Recommended method for generating data stored in memory. Called in initialization.
View Source
def generate_data(self) -> None:
"""Recommended method for generating data stored in memory. Called in initialization."""
...
get_server⚓︎
def get_server(
self
)
Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
| Type | Description |
|---|---|
| dict | the Flask server component of the Dash app |
View Source
def get_server(self):
"""Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
dict: the Flask `server` component of the Dash app
"""
return self.app.server
initialization⚓︎
def initialization(
self
) -> None
Initialize ids with self.register_uniq_ids([...]) and other one-time actions.
View Source
def initialization(self) -> None:
"""Initialize ids with `self.register_uniq_ids([...])` and other one-time actions."""
super().initialization()
self.register_uniq_ids(self.app_ids)
override_module_defaults⚓︎
def override_module_defaults(
self
) -> None
Override default values from modules.
View Source
def override_module_defaults(self) -> None:
"""Override default values from modules."""
...
register_uniq_ids⚓︎
def register_uniq_ids(
self,
app_ids: List[str]
) -> None
Register the app_ids to the corresponding global_id in the self._il lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers self._il
which are a list of globally unique ids (incorporating this App’s unique self.name) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Parameters:
| Name | Description |
|---|---|
| app_ids | list of strings that are unique within this App |
View Source
def register_uniq_ids(self, app_ids: List[str]) -> None:
"""Register the `app_ids` to the corresponding global_id in the `self._il` lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers `self._il`
which are a list of globally unique ids (incorporating this App's unique `self.name`) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Args:
app_ids: list of strings that are unique within this App
"""
self._il = deepcopy(self._il)
for app_id in app_ids:
self._il[app_id] = f'{self.name}-{app_id}'.replace(' ', '-')
return_layout⚓︎
def return_layout(
self
) -> dict
Return Dash application layout.
Returns:
| Type | Description |
|---|---|
| dict | Dash HTML object. Default is simple HTML text |
View Source
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object. Default is simple HTML text
"""
return html.Div(['Welcome to the BaseApp! Override return_layout() in child class.']) # pragma: no cover
run⚓︎
def run(
self,
**dash_kwargs: dict
) -> None
Launch the Dash server instance.
Parameters:
| Name | Description |
|---|---|
| **dash_kwargs | keyword arguments for Dash.run_server() |
View Source
def run(self, **dash_kwargs: dict) -> None:
"""Launch the Dash server instance.
Args:
**dash_kwargs: keyword arguments for `Dash.run_server()`
"""
self.app.run_server(**dash_kwargs) # pragma: no cover
verify_app_initialization⚓︎
def verify_app_initialization(
self
) -> None
Check that the app was properly initialized.
Raises:
| Type | Description |
|---|---|
| RuntimeError | if child class has not called self.register_uniq_ids |
View Source
def verify_app_initialization(self) -> None:
"""Check that the app was properly initialized.
Raises:
RuntimeError: if child class has not called `self.register_uniq_ids`
"""
if not self._il.keys(): # pragma: no cover
raise RuntimeError('Child class must first call `self.register_uniq_ids(__)` before self.run()')
AppWithTabs⚓︎
class AppWithTabs(
app: Union[dash.dash.Dash, NoneType] = None
)
View Source
class AppWithTabs(AppWithNavigation):
"""Base class for building Dash Application with tabs."""
# App ids
id_tabs_content = 'tabs-wrapper'
id_tabs_select = 'tabs-content'
app_ids = [id_tabs_content, id_tabs_select]
"""List of all ids for the top-level tab view. Will be mapped to `self._il` for globally unique ids."""
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object
"""
tabs = [dcc.Tab(label=name, value=name) for name, tab in self.nav_lookup.items()]
return html.Div(
children=[
dcc.Tabs(
id=self._il[self.id_tabs_select], value=list(self.nav_lookup.keys())[0],
children=tabs,
),
html.Div(id=self._il[self.id_tabs_content]),
],
)
def create_callbacks(self) -> None:
"""Register the navigation callback."""
outputs = [(self.id_tabs_content, 'children')]
inputs = [(self.id_tabs_select, 'value')]
@self.callback(outputs, inputs, [])
def render_tab(tab_name):
return [self.nav_layouts[tab_name]]
Ancestors (in MRO)⚓︎
- dash_charts.utils_app_with_navigation.AppWithNavigation
- dash_charts.utils_app.AppBase
Descendants⚓︎
- dash_charts.utils_app_with_navigation.FullScreenAppWithTabs
Class variables⚓︎
app
app_ids
List of all ids for the top-level tab view. Will be mapped to self._il for globally unique ids.
external_stylesheets
id_tabs_content
id_tabs_select
init_app_kwargs
modules
name
nav_layouts
nav_lookup
nsi
validation_layout
Methods⚓︎
callback⚓︎
def callback(
self,
outputs,
inputs,
states,
pic: bool = False,
**kwargs: dict
)
Return app callback decorator based on provided components.
Parameters:
| Name | Description |
|---|---|
| outputs | list of tuples with app_id and property name |
| inputs | list of tuples with app_id and property name |
| states | list of tuples with app_id and property name |
| pic | If True, prevent call on page load (prevent_initial_call). Default is False |
| **kwargs | any additional keyword arguments for self.app.callback |
Returns:
| Type | Description |
|---|---|
| dict | result of self.app.callback() |
View Source
def callback(self, outputs, inputs, states, pic: bool = False, **kwargs: dict):
"""Return app callback decorator based on provided components.
Args:
outputs: list of tuples with app_id and property name
inputs: list of tuples with app_id and property name
states: list of tuples with app_id and property name
pic: If True, prevent call on page load (`prevent_initial_call`). Default is False
**kwargs: any additional keyword arguments for `self.app.callback`
Returns:
dict: result of `self.app.callback()`
"""
return self.app.callback(
*format_app_callback(self._il, outputs, inputs, states),
prevent_initial_call=pic,
**kwargs,
)
create⚓︎
def create(
self,
**kwargs
)
Create each navigation componet, storing the layout. Then parent class to create application.
Parameters:
| Name | Description |
|---|---|
| kwargs | keyword arguments passed to self.create |
View Source
def create(self, **kwargs):
"""Create each navigation componet, storing the layout. Then parent class to create application.
Args:
kwargs: keyword arguments passed to `self.create`
"""
# Initialize the lookup for each tab then configure each tab
self.nav_lookup = OrderedDict([(tab.name, tab) for tab in self.define_nav_elements()])
self.nav_layouts = {}
for nav_name, nav in self.nav_lookup.items():
nav.create(assign_layout=False)
self.nav_layouts[nav_name] = nav.return_layout()
# Store validation_layout that is later used for callback verification in base class
self.validation_layout = [*map(deepcopy, self.nav_layouts.values())]
# Initialize parent application that handles navigation
super().create(**kwargs)
create_callbacks⚓︎
def create_callbacks(
self
) -> None
Register the navigation callback.
View Source
def create_callbacks(self) -> None:
"""Register the navigation callback."""
outputs = [(self.id_tabs_content, 'children')]
inputs = [(self.id_tabs_select, 'value')]
@self.callback(outputs, inputs, [])
def render_tab(tab_name):
return [self.nav_layouts[tab_name]]
create_elements⚓︎
def create_elements(
self
) -> None
Override method as not needed at navigation-level.
View Source
def create_elements(self) -> None:
"""Override method as not needed at navigation-level."""
... # pragma: no cover
define_nav_elements⚓︎
def define_nav_elements(
self
)
Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex [AppBase(self.app)] in the order each tab is rendered
Raises:
| Type | Description |
|---|---|
| NotImplementedError | Child class must implement this method |
View Source
def define_nav_elements(self):
"""Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex `[AppBase(self.app)]` in the order each tab is rendered
Raises:
NotImplementedError: Child class must implement this method
"""
raise NotImplementedError('define_nav_elements must be implemented by child class') # pragma: no cover
generate_data⚓︎
def generate_data(
self
) -> None
Recommended method for generating data stored in memory. Called in initialization.
View Source
def generate_data(self) -> None:
"""Recommended method for generating data stored in memory. Called in initialization."""
...
get_server⚓︎
def get_server(
self
)
Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
| Type | Description |
|---|---|
| dict | the Flask server component of the Dash app |
View Source
def get_server(self):
"""Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
dict: the Flask `server` component of the Dash app
"""
return self.app.server
initialization⚓︎
def initialization(
self
) -> None
Initialize ids with self.register_uniq_ids([...]) and other one-time actions.
View Source
def initialization(self) -> None:
"""Initialize ids with `self.register_uniq_ids([...])` and other one-time actions."""
super().initialization()
self.register_uniq_ids(self.app_ids)
override_module_defaults⚓︎
def override_module_defaults(
self
) -> None
Override default values from modules.
View Source
def override_module_defaults(self) -> None:
"""Override default values from modules."""
...
register_uniq_ids⚓︎
def register_uniq_ids(
self,
app_ids: List[str]
) -> None
Register the app_ids to the corresponding global_id in the self._il lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers self._il
which are a list of globally unique ids (incorporating this App’s unique self.name) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Parameters:
| Name | Description |
|---|---|
| app_ids | list of strings that are unique within this App |
View Source
def register_uniq_ids(self, app_ids: List[str]) -> None:
"""Register the `app_ids` to the corresponding global_id in the `self._il` lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers `self._il`
which are a list of globally unique ids (incorporating this App's unique `self.name`) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Args:
app_ids: list of strings that are unique within this App
"""
self._il = deepcopy(self._il)
for app_id in app_ids:
self._il[app_id] = f'{self.name}-{app_id}'.replace(' ', '-')
return_layout⚓︎
def return_layout(
self
) -> dict
Return Dash application layout.
Returns:
| Type | Description |
|---|---|
| dict | Dash HTML object |
View Source
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object
"""
tabs = [dcc.Tab(label=name, value=name) for name, tab in self.nav_lookup.items()]
return html.Div(
children=[
dcc.Tabs(
id=self._il[self.id_tabs_select], value=list(self.nav_lookup.keys())[0],
children=tabs,
),
html.Div(id=self._il[self.id_tabs_content]),
],
)
run⚓︎
def run(
self,
**dash_kwargs: dict
) -> None
Launch the Dash server instance.
Parameters:
| Name | Description |
|---|---|
| **dash_kwargs | keyword arguments for Dash.run_server() |
View Source
def run(self, **dash_kwargs: dict) -> None:
"""Launch the Dash server instance.
Args:
**dash_kwargs: keyword arguments for `Dash.run_server()`
"""
self.app.run_server(**dash_kwargs) # pragma: no cover
verify_app_initialization⚓︎
def verify_app_initialization(
self
) -> None
Check that the app was properly initialized.
Raises:
| Type | Description |
|---|---|
| RuntimeError | if child class has not called self.register_uniq_ids |
View Source
def verify_app_initialization(self) -> None:
"""Check that the app was properly initialized.
Raises:
RuntimeError: if child class has not called `self.register_uniq_ids`
"""
if not self._il.keys(): # pragma: no cover
raise RuntimeError('Child class must first call `self.register_uniq_ids(__)` before self.run()')
FullScreenAppWithTabs⚓︎
class FullScreenAppWithTabs(
app: Union[dash.dash.Dash, NoneType] = None
)
View Source
class FullScreenAppWithTabs(AppWithTabs): # noqa: H601
"""Base class for building Dash Application with tabs that uses the full window."""
tabs_location = 'left'
"""Tab orientation setting. One of `(left, top, bottom, right)`."""
tabs_margin = '10%'
"""Adjust this setting based on the width or height of the tabs to prevent the content from overlapping the tabs."""
tabs_compact = False
"""Boolean setting to toggle between a padded tab layout if False and a minimal compact version if True."""
def verify_app_initialization(self):
"""Check that the app was properly initialized.
Raises:
RuntimeError: if child class has not called `self.register_uniq_ids`
"""
super().verify_app_initialization()
allowed_locations = ('left', 'top', 'bottom', 'right')
if self.tabs_location not in allowed_locations: # pragma: no cover
raise RuntimeError(f'`self.tabs_location = {self.tabs_location}` is not in {allowed_locations}')
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object
"""
return html.Div(
children=[
self.tab_menu(),
html.Div(
style={f'margin-{self.tabs_location}': self.tabs_margin},
children=[html.Div(id=self._il[self.id_tabs_content])],
),
],
)
def generate_tab_kwargs(self):
"""Create the tab keyword arguments. Intended to be modified through inheritance.
Returns:
tuple: keyword arguments and styling for the dcc.Tab elements
- tab_kwargs: with at minimum keys `(style, selected_style)` for dcc.Tab
- tabs_kwargs: to be passed to dcc.Tabs
- tabs_style: style for the dcc.Tabs HTML element
"""
# Unselected tab style
if self.tabs_compact:
tab_style = {'padding': '2px 4px 2px 4px'}
tabs_padding = '6px 0 0 2px'
else:
tab_style = {'padding': '10px 20px 10px 20px'}
tabs_padding = '15px 0 0 5px'
# Extend tab style for selected case
selected_style = deepcopy(tab_style)
opposite_lookup = {'top': 'bottom', 'bottom': 'top', 'left': 'right', 'right': 'left'}
tabs_style = { # noqa: ECE001
'backgroundColor': '#F9F9F9',
'padding': tabs_padding,
'position': 'fixed',
'zIndex': '999',
f'border{opposite_lookup[self.tabs_location].title()}': '1px solid #d6d6d6',
self.tabs_location: '0',
}
if self.tabs_location in ['left', 'right']:
# Configure for vertical case
selected_style['border-left'] = '3px solid #119DFF'
tabs_kwargs = {
'vertical': True,
'style': {'width': '100%'},
'parent_style': {'width': '100%'},
}
tabs_style['top'] = '0'
tabs_style['bottom'] = '0'
tabs_style['width'] = 'auto'
else:
# Configure for horizontal case
selected_style['border-top'] = '3px solid #119DFF'
tabs_kwargs = {}
tabs_style['height'] = 'auto'
tabs_style['right'] = '0'
tabs_style['left'] = '0'
tab_kwargs = {'style': tab_style, 'selected_style': selected_style}
return (tab_kwargs, tabs_kwargs, tabs_style)
def tab_menu(self):
"""Return the HTML elements for the tab menu.
Returns:
dict: Dash HTML object
"""
tab_kwargs, tabs_kwargs, tabs_style = self.generate_tab_kwargs()
tabs = [dcc.Tab(label=name, value=name, **tab_kwargs) for name, tab in self.nav_lookup.items()]
return html.Div(
children=[
dcc.Tabs(
id=self._il[self.id_tabs_select], value=list(self.nav_lookup.keys())[0],
children=tabs, **tabs_kwargs,
),
], style=tabs_style,
)
Ancestors (in MRO)⚓︎
- dash_charts.utils_app_with_navigation.AppWithTabs
- dash_charts.utils_app_with_navigation.AppWithNavigation
- dash_charts.utils_app.AppBase
Descendants⚓︎
- dash_charts.app_px.InteractivePXApp
Class variables⚓︎
app
app_ids
external_stylesheets
id_tabs_content
id_tabs_select
init_app_kwargs
modules
name
nav_layouts
nav_lookup
nsi
tabs_compact
Boolean setting to toggle between a padded tab layout if False and a minimal compact version if True.
tabs_location
Tab orientation setting. One of (left, top, bottom, right).
tabs_margin
Adjust this setting based on the width or height of the tabs to prevent the content from overlapping the tabs.
validation_layout
Methods⚓︎
callback⚓︎
def callback(
self,
outputs,
inputs,
states,
pic: bool = False,
**kwargs: dict
)
Return app callback decorator based on provided components.
Parameters:
| Name | Description |
|---|---|
| outputs | list of tuples with app_id and property name |
| inputs | list of tuples with app_id and property name |
| states | list of tuples with app_id and property name |
| pic | If True, prevent call on page load (prevent_initial_call). Default is False |
| **kwargs | any additional keyword arguments for self.app.callback |
Returns:
| Type | Description |
|---|---|
| dict | result of self.app.callback() |
View Source
def callback(self, outputs, inputs, states, pic: bool = False, **kwargs: dict):
"""Return app callback decorator based on provided components.
Args:
outputs: list of tuples with app_id and property name
inputs: list of tuples with app_id and property name
states: list of tuples with app_id and property name
pic: If True, prevent call on page load (`prevent_initial_call`). Default is False
**kwargs: any additional keyword arguments for `self.app.callback`
Returns:
dict: result of `self.app.callback()`
"""
return self.app.callback(
*format_app_callback(self._il, outputs, inputs, states),
prevent_initial_call=pic,
**kwargs,
)
create⚓︎
def create(
self,
**kwargs
)
Create each navigation componet, storing the layout. Then parent class to create application.
Parameters:
| Name | Description |
|---|---|
| kwargs | keyword arguments passed to self.create |
View Source
def create(self, **kwargs):
"""Create each navigation componet, storing the layout. Then parent class to create application.
Args:
kwargs: keyword arguments passed to `self.create`
"""
# Initialize the lookup for each tab then configure each tab
self.nav_lookup = OrderedDict([(tab.name, tab) for tab in self.define_nav_elements()])
self.nav_layouts = {}
for nav_name, nav in self.nav_lookup.items():
nav.create(assign_layout=False)
self.nav_layouts[nav_name] = nav.return_layout()
# Store validation_layout that is later used for callback verification in base class
self.validation_layout = [*map(deepcopy, self.nav_layouts.values())]
# Initialize parent application that handles navigation
super().create(**kwargs)
create_callbacks⚓︎
def create_callbacks(
self
) -> None
Register the navigation callback.
View Source
def create_callbacks(self) -> None:
"""Register the navigation callback."""
outputs = [(self.id_tabs_content, 'children')]
inputs = [(self.id_tabs_select, 'value')]
@self.callback(outputs, inputs, [])
def render_tab(tab_name):
return [self.nav_layouts[tab_name]]
create_elements⚓︎
def create_elements(
self
) -> None
Override method as not needed at navigation-level.
View Source
def create_elements(self) -> None:
"""Override method as not needed at navigation-level."""
... # pragma: no cover
define_nav_elements⚓︎
def define_nav_elements(
self
)
Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex [AppBase(self.app)] in the order each tab is rendered
Raises:
| Type | Description |
|---|---|
| NotImplementedError | Child class must implement this method |
View Source
def define_nav_elements(self):
"""Return list of initialized pages or tabs accordingly.
Should return, list: each item is an initialized app (ex `[AppBase(self.app)]` in the order each tab is rendered
Raises:
NotImplementedError: Child class must implement this method
"""
raise NotImplementedError('define_nav_elements must be implemented by child class') # pragma: no cover
generate_data⚓︎
def generate_data(
self
) -> None
Recommended method for generating data stored in memory. Called in initialization.
View Source
def generate_data(self) -> None:
"""Recommended method for generating data stored in memory. Called in initialization."""
...
generate_tab_kwargs⚓︎
def generate_tab_kwargs(
self
)
Create the tab keyword arguments. Intended to be modified through inheritance.
Returns:
| Type | Description |
|---|---|
| tuple | keyword arguments and styling for the dcc.Tab elements |
- tab_kwargs: with at minimum keys (style, selected_style) for dcc.Tab |
|
| - tabs_kwargs: to be passed to dcc.Tabs | |
| - tabs_style: style for the dcc.Tabs HTML element |
View Source
def generate_tab_kwargs(self):
"""Create the tab keyword arguments. Intended to be modified through inheritance.
Returns:
tuple: keyword arguments and styling for the dcc.Tab elements
- tab_kwargs: with at minimum keys `(style, selected_style)` for dcc.Tab
- tabs_kwargs: to be passed to dcc.Tabs
- tabs_style: style for the dcc.Tabs HTML element
"""
# Unselected tab style
if self.tabs_compact:
tab_style = {'padding': '2px 4px 2px 4px'}
tabs_padding = '6px 0 0 2px'
else:
tab_style = {'padding': '10px 20px 10px 20px'}
tabs_padding = '15px 0 0 5px'
# Extend tab style for selected case
selected_style = deepcopy(tab_style)
opposite_lookup = {'top': 'bottom', 'bottom': 'top', 'left': 'right', 'right': 'left'}
tabs_style = { # noqa: ECE001
'backgroundColor': '#F9F9F9',
'padding': tabs_padding,
'position': 'fixed',
'zIndex': '999',
f'border{opposite_lookup[self.tabs_location].title()}': '1px solid #d6d6d6',
self.tabs_location: '0',
}
if self.tabs_location in ['left', 'right']:
# Configure for vertical case
selected_style['border-left'] = '3px solid #119DFF'
tabs_kwargs = {
'vertical': True,
'style': {'width': '100%'},
'parent_style': {'width': '100%'},
}
tabs_style['top'] = '0'
tabs_style['bottom'] = '0'
tabs_style['width'] = 'auto'
else:
# Configure for horizontal case
selected_style['border-top'] = '3px solid #119DFF'
tabs_kwargs = {}
tabs_style['height'] = 'auto'
tabs_style['right'] = '0'
tabs_style['left'] = '0'
tab_kwargs = {'style': tab_style, 'selected_style': selected_style}
return (tab_kwargs, tabs_kwargs, tabs_style)
get_server⚓︎
def get_server(
self
)
Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
| Type | Description |
|---|---|
| dict | the Flask server component of the Dash app |
View Source
def get_server(self):
"""Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
dict: the Flask `server` component of the Dash app
"""
return self.app.server
initialization⚓︎
def initialization(
self
) -> None
Initialize ids with self.register_uniq_ids([...]) and other one-time actions.
View Source
def initialization(self) -> None:
"""Initialize ids with `self.register_uniq_ids([...])` and other one-time actions."""
super().initialization()
self.register_uniq_ids(self.app_ids)
override_module_defaults⚓︎
def override_module_defaults(
self
) -> None
Override default values from modules.
View Source
def override_module_defaults(self) -> None:
"""Override default values from modules."""
...
register_uniq_ids⚓︎
def register_uniq_ids(
self,
app_ids: List[str]
) -> None
Register the app_ids to the corresponding global_id in the self._il lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers self._il
which are a list of globally unique ids (incorporating this App’s unique self.name) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Parameters:
| Name | Description |
|---|---|
| app_ids | list of strings that are unique within this App |
View Source
def register_uniq_ids(self, app_ids: List[str]) -> None:
"""Register the `app_ids` to the corresponding global_id in the `self._il` lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers `self._il`
which are a list of globally unique ids (incorporating this App's unique `self.name`) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Args:
app_ids: list of strings that are unique within this App
"""
self._il = deepcopy(self._il)
for app_id in app_ids:
self._il[app_id] = f'{self.name}-{app_id}'.replace(' ', '-')
return_layout⚓︎
def return_layout(
self
) -> dict
Return Dash application layout.
Returns:
| Type | Description |
|---|---|
| dict | Dash HTML object |
View Source
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object
"""
return html.Div(
children=[
self.tab_menu(),
html.Div(
style={f'margin-{self.tabs_location}': self.tabs_margin},
children=[html.Div(id=self._il[self.id_tabs_content])],
),
],
)
run⚓︎
def run(
self,
**dash_kwargs: dict
) -> None
Launch the Dash server instance.
Parameters:
| Name | Description |
|---|---|
| **dash_kwargs | keyword arguments for Dash.run_server() |
View Source
def run(self, **dash_kwargs: dict) -> None:
"""Launch the Dash server instance.
Args:
**dash_kwargs: keyword arguments for `Dash.run_server()`
"""
self.app.run_server(**dash_kwargs) # pragma: no cover
tab_menu⚓︎
def tab_menu(
self
)
Return the HTML elements for the tab menu.
Returns:
| Type | Description |
|---|---|
| dict | Dash HTML object |
View Source
def tab_menu(self):
"""Return the HTML elements for the tab menu.
Returns:
dict: Dash HTML object
"""
tab_kwargs, tabs_kwargs, tabs_style = self.generate_tab_kwargs()
tabs = [dcc.Tab(label=name, value=name, **tab_kwargs) for name, tab in self.nav_lookup.items()]
return html.Div(
children=[
dcc.Tabs(
id=self._il[self.id_tabs_select], value=list(self.nav_lookup.keys())[0],
children=tabs, **tabs_kwargs,
),
], style=tabs_style,
)
verify_app_initialization⚓︎
def verify_app_initialization(
self
)
Check that the app was properly initialized.
Raises:
| Type | Description |
|---|---|
| RuntimeError | if child class has not called self.register_uniq_ids |
View Source
def verify_app_initialization(self):
"""Check that the app was properly initialized.
Raises:
RuntimeError: if child class has not called `self.register_uniq_ids`
"""
super().verify_app_initialization()
allowed_locations = ('left', 'top', 'bottom', 'right')
if self.tabs_location not in allowed_locations: # pragma: no cover
raise RuntimeError(f'`self.tabs_location = {self.tabs_location}` is not in {allowed_locations}')
StaticTab⚓︎
class StaticTab(
app: Union[dash.dash.Dash, NoneType] = None
)
View Source
class StaticTab(AppBase):
"""Simple App without charts or callbacks."""
basic_style = {
'marginLeft': 'auto',
'marginRight': 'auto',
'maxWidth': '1000px',
'paddingTop': '10px',
}
def initialization(self) -> None:
"""Initialize ids with `self.register_uniq_ids([...])` and other one-time actions."""
super().initialization()
self.register_uniq_ids(['N/A'])
def create_elements(self) -> None:
"""Initialize the charts, tables, and other Dash elements.."""
...
def create_callbacks(self) -> None:
"""Register callbacks necessary for this tab."""
...
Ancestors (in MRO)⚓︎
- dash_charts.utils_app.AppBase
Class variables⚓︎
basic_style
external_stylesheets
init_app_kwargs
modules
name
nsi
validation_layout
Methods⚓︎
callback⚓︎
def callback(
self,
outputs,
inputs,
states,
pic: bool = False,
**kwargs: dict
)
Return app callback decorator based on provided components.
Parameters:
| Name | Description |
|---|---|
| outputs | list of tuples with app_id and property name |
| inputs | list of tuples with app_id and property name |
| states | list of tuples with app_id and property name |
| pic | If True, prevent call on page load (prevent_initial_call). Default is False |
| **kwargs | any additional keyword arguments for self.app.callback |
Returns:
| Type | Description |
|---|---|
| dict | result of self.app.callback() |
View Source
def callback(self, outputs, inputs, states, pic: bool = False, **kwargs: dict):
"""Return app callback decorator based on provided components.
Args:
outputs: list of tuples with app_id and property name
inputs: list of tuples with app_id and property name
states: list of tuples with app_id and property name
pic: If True, prevent call on page load (`prevent_initial_call`). Default is False
**kwargs: any additional keyword arguments for `self.app.callback`
Returns:
dict: result of `self.app.callback()`
"""
return self.app.callback(
*format_app_callback(self._il, outputs, inputs, states),
prevent_initial_call=pic,
**kwargs,
)
create⚓︎
def create(
self,
assign_layout: bool = True
) -> None
Create the ids, app charts, layout, callbacks, and optional modules.
Parameters:
| Name | Description |
|---|---|
| assign_layout | if True, will assign self.app.layout. If False, must call self.return_layout separately.Default is True |
Raises:
| Type | Description |
|---|---|
| NotImplementedError | if child class has not set the self.name data member |
View Source
def create(self, assign_layout: bool = True) -> None: # noqa: CCR001
"""Create the ids, app charts, layout, callbacks, and optional modules.
Args:
assign_layout: if True, will assign `self.app.layout`. If False, must call `self.return_layout` separately.
Default is True
Raises:
NotImplementedError: if child class has not set the `self.name` data member
"""
if self.name is None: # pragma: no cover
raise NotImplementedError('Child class must set `self.name` to a unique string for this app')
# Initialize app and each module
self.initialization()
for mod in self.modules:
self.register_uniq_ids(mod.all_ids)
self.override_module_defaults() # Call optional override method
# Create charts for app and each module
self.create_elements()
for mod in self.modules:
mod.create_elements(self._il)
# Create app layout. User must call the return_layout method from each module within own return_layout method
if assign_layout:
self.app.layout = self.return_layout()
if assign_layout and self.validation_layout:
self.app.validation_layout = [deepcopy(self.app.layout)] + self.validation_layout
pprint('\n\nValidationLayout?')
pprint(self.app.validation_layout)
# Create callbacks for app and each module
self.create_callbacks()
for mod in self.modules:
mod.create_callbacks(self)
self.verify_app_initialization()
create_callbacks⚓︎
def create_callbacks(
self
) -> None
Register callbacks necessary for this tab.
View Source
def create_callbacks(self) -> None:
"""Register callbacks necessary for this tab."""
...
create_elements⚓︎
def create_elements(
self
) -> None
Initialize the charts, tables, and other Dash elements..
View Source
def create_elements(self) -> None:
"""Initialize the charts, tables, and other Dash elements.."""
...
generate_data⚓︎
def generate_data(
self
) -> None
Recommended method for generating data stored in memory. Called in initialization.
View Source
def generate_data(self) -> None:
"""Recommended method for generating data stored in memory. Called in initialization."""
...
get_server⚓︎
def get_server(
self
)
Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
| Type | Description |
|---|---|
| dict | the Flask server component of the Dash app |
View Source
def get_server(self):
"""Retrieve server from app instance for production hosting with green unicorn, waitress, IIS, etc.
Returns:
dict: the Flask `server` component of the Dash app
"""
return self.app.server
initialization⚓︎
def initialization(
self
) -> None
Initialize ids with self.register_uniq_ids([...]) and other one-time actions.
View Source
def initialization(self) -> None:
"""Initialize ids with `self.register_uniq_ids([...])` and other one-time actions."""
super().initialization()
self.register_uniq_ids(['N/A'])
override_module_defaults⚓︎
def override_module_defaults(
self
) -> None
Override default values from modules.
View Source
def override_module_defaults(self) -> None:
"""Override default values from modules."""
...
register_uniq_ids⚓︎
def register_uniq_ids(
self,
app_ids: List[str]
) -> None
Register the app_ids to the corresponding global_id in the self._il lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers self._il
which are a list of globally unique ids (incorporating this App’s unique self.name) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Parameters:
| Name | Description |
|---|---|
| app_ids | list of strings that are unique within this App |
View Source
def register_uniq_ids(self, app_ids: List[str]) -> None:
"""Register the `app_ids` to the corresponding global_id in the `self._il` lookup dictionary.
The app_ids must be unique within this App so that a layout can be created. This method registers `self._il`
which are a list of globally unique ids (incorporating this App's unique `self.name`) allowing for the child
class of this base App to be resused multiple times within a tabbed or multi-page application without
id-collision
Args:
app_ids: list of strings that are unique within this App
"""
self._il = deepcopy(self._il)
for app_id in app_ids:
self._il[app_id] = f'{self.name}-{app_id}'.replace(' ', '-')
return_layout⚓︎
def return_layout(
self
) -> dict
Return Dash application layout.
Returns:
| Type | Description |
|---|---|
| dict | Dash HTML object. Default is simple HTML text |
View Source
def return_layout(self) -> dict:
"""Return Dash application layout.
Returns:
dict: Dash HTML object. Default is simple HTML text
"""
return html.Div(['Welcome to the BaseApp! Override return_layout() in child class.']) # pragma: no cover
run⚓︎
def run(
self,
**dash_kwargs: dict
) -> None
Launch the Dash server instance.
Parameters:
| Name | Description |
|---|---|
| **dash_kwargs | keyword arguments for Dash.run_server() |
View Source
def run(self, **dash_kwargs: dict) -> None:
"""Launch the Dash server instance.
Args:
**dash_kwargs: keyword arguments for `Dash.run_server()`
"""
self.app.run_server(**dash_kwargs) # pragma: no cover
verify_app_initialization⚓︎
def verify_app_initialization(
self
) -> None
Check that the app was properly initialized.
Raises:
| Type | Description |
|---|---|
| RuntimeError | if child class has not called self.register_uniq_ids |
View Source
def verify_app_initialization(self) -> None:
"""Check that the app was properly initialized.
Raises:
RuntimeError: if child class has not called `self.register_uniq_ids`
"""
if not self._il.keys(): # pragma: no cover
raise RuntimeError('Child class must first call `self.register_uniq_ids(__)` before self.run()')
Created: August 5, 2022